package com.lost.octopus.es.processor.util;

import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.ClassUtils;
import org.elasticsearch.common.util.concurrent.EsRejectedExecutionException;
import org.springframework.data.elasticsearch.annotations.Document;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

/**
 * 反射工具类
 * @author zhangbh
 */
@Log4j2
public final class ReflectUtil {

    public static Class<?> getEsIdType(final Class<?> clazz) {
        if (ClassUtils.isPrimitiveOrWrapper(clazz) || String.class.equals(clazz)) {
            log.debug("ID 类型是基本类型或包装类型: " + clazz.getSimpleName());
            return clazz;
        }
        throw new IllegalArgumentException("获取 idType 失败,非基础类型无法处理,clazz " + clazz.getName());
    }

    /**
     * 获取 范型 class
     * @param clazz 类型
     * @param index 泛型idx
     * @return 获取泛型class
     */
    public static Class<?> getSuperClassGenericType(final Class<?> clazz, final int index) {
        Type genType = clazz.getGenericSuperclass();
        if (!(genType instanceof ParameterizedType)) {
            log.warn(String.format("Warn: %s's superclass not ParameterizedType", clazz.getSimpleName()));
            return Object.class;
        } else {
            Type[] params = ((ParameterizedType) genType).getActualTypeArguments();
            if (index < params.length && index >= 0) {
                if (!(params[index] instanceof Class)) {
                    log.warn(String.format("Warn: %s not set the actual class on superclass generic parameter", clazz.getSimpleName()));
                    return Object.class;
                } else {
                    return (Class<?>) params[index];
                }
            } else {
                log.warn(String.format("Warn: Index: %s, Size of %s's Parameterized Type: %s .", index, clazz.getSimpleName(), params.length));
                return Object.class;
            }
        }
    }

    /**
     * 获取索引名称
     */
    public static String getIndexNameByClazz(final Class<?> clazz) {

        if (clazz.isAnnotationPresent(Document.class)) {
            Document document = clazz.getAnnotation(Document.class);
            return document.indexName();
        }
        log.error("不是ES的实体，该方法不适用");
        throw new EsRejectedExecutionException("ES实体必须存在 Document 注解");
    }

}
